package jia.core.processors;

import jia.core.Compass;
import jia.core.GameStateManager;
import jia.core.InputProcessor;
import jia.core.Module;
import jia.core.Space;
import jia.core.UiManager;
import jia.core.Wall;
import jia.core.flags.WallFlags;
import jia.core.event.KeypressUiEvent;
import jia.core.event.UiEvent;
import jia.core.state.PlayerState;
import org.apache.log4j.Logger;

import javax.vecmath.Vector2d;
import java.awt.event.KeyEvent;
import java.util.GregorianCalendar;

// ====================================================
/**
 * @author Alec Lanter
 */
public class BasicInputProcessor implements InputProcessor{
	private GameStateManager mgr;
	private static final Logger log = Logger.getLogger(BasicInputProcessor.class);

	public BasicInputProcessor(){
	}

	public BasicInputProcessor(GameStateManager gameState){
		this.mgr = gameState;
	}

	// ====================================================
	/**
	 * @see net.sf.jia.core.InputProcessor#registerGameState(net.sf.jia.core.GameStateManager)
	 */
	public void registerGameState(GameStateManager gameState){
		mgr = gameState;
	}

	// ====================================================
	/**
	 * @see net.sf.jia.core.InputProcessor#processUiEvent(net.sf.jia.framework.event.UiEvent)
	 */
	public void processUiEvent(UiEvent evt){
		if(evt instanceof KeypressUiEvent) {
			handleKeypress((KeypressUiEvent) evt);
		}
	}

	//====================================================
	/**
	 */
	protected void moveForward(){
		PlayerState ps = mgr.getPlayerState();
		UiManager uiMgr = mgr.getUiManager();
		Compass facing = ps.getFacing();
		Vector2d position = ps.getPosition();
		int dx = 0;
		int dy = 0;
		switch(facing.getDirectionalValue()) {
			case Compass.NORTH_VAL:
				if(isPassable(Compass.NORTH)) {
					dy = -1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall					
				}
				break;
			case Compass.SOUTH_VAL:
				if(isPassable(Compass.SOUTH)) {
					dy = 1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			case Compass.EAST_VAL:
				if(isPassable(Compass.EAST)) {
					dx = 1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			case Compass.WEST_VAL:
				if(isPassable(Compass.WEST)) {
					dx = -1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			default:
				//TODO:  Fire a sound event indicating the player hit a wall
				return;
		}
		position.x += dx;
		position.y += dy;
	}

	//====================================================
	/**
	 * @param wallDir
	 *
	 * @return
	 */
	protected boolean isPassable(Compass wallDir){
		Module module = mgr.getPlayerState().getCurrentModule();
		Vector2d position = mgr.getPlayerState().getPosition();
		Space currentSpace = module.getSpace(position);

		//get a wall object for the direction you are facing
		Wall testWall = currentSpace.getWall(wallDir);
		//if there is no wall, then it must be open
		if(testWall != null) {
			return testWall.getFlags().hasFlag(WallFlags.OPEN);
		} else {
			return true;
		}
	}

	//====================================================
	/**
	 */
	protected void moveBackward(){
		PlayerState ps = mgr.getPlayerState();
		UiManager uiMgr = mgr.getUiManager();
		Compass facing = ps.getFacing();
		Vector2d position = ps.getPosition();
		int dx = 0;
		int dy = 0;
		switch(facing.getDirectionalValue()) {
			case Compass.NORTH_VAL:
				if(isPassable(Compass.SOUTH)) {
					dy = -1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall					
				}
				break;
			case Compass.SOUTH_VAL:
				if(isPassable(Compass.NORTH)) {
					dy = 1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			case Compass.EAST_VAL:
				if(isPassable(Compass.WEST)) {
					dx = 1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			case Compass.WEST_VAL:
				if(isPassable(Compass.EAST)) {
					dx = -1;
					//TODO:  Fire a sound event indicating a step was taken
				} else {
					uiMgr.setDialogText(uiMgr.getDialoguePane().getText() + "\n" + GregorianCalendar.HOUR + ":" + GregorianCalendar.MINUTE + ":" + GregorianCalendar.SECOND + " - Ouch! ");
					//TODO:  Fire a sound event indicating the player hit a wall
				}
				break;
			default:
				// TODO: Fire text event to notify player of bumping into something
				return;
		}
		position.x -= dx;
		position.y -= dy;
	}

	//===============================================
	/**
	 * @param evt
	 */
	protected void handleKeypress(KeypressUiEvent evt){
		int keyCode = evt.getKeyCode();
		switch(keyCode) {
			case KeyEvent.VK_UP:
			case KeyEvent.VK_KP_UP:
			case KeyEvent.VK_W:
				moveForward();
				break;
			case KeyEvent.VK_DOWN:
			case KeyEvent.VK_KP_DOWN:
			case KeyEvent.VK_S:
				moveBackward();
				break;
			case KeyEvent.VK_LEFT:
			case KeyEvent.VK_KP_LEFT:
			case KeyEvent.VK_A:
				turnLeft();
				break;
			case KeyEvent.VK_RIGHT:
			case KeyEvent.VK_KP_RIGHT:
			case KeyEvent.VK_D:
				turnRight();
				break;
			default:
				return;
		}
		mgr.notifyPlayerStateChanged();
	}

	//===============================================
	/**
	 */
	protected void turnLeft(){
		Compass facing = mgr.getPlayerState().getFacing();
		mgr.getPlayerState().setFacing(Compass.add(Compass.WEST, facing));
		//TODO:  Fire a sound event indicating a step was taken
	}

	//===============================================
	/**
	 */
	protected void turnRight(){
		Compass facing = mgr.getPlayerState().getFacing();
		mgr.getPlayerState().setFacing(Compass.add(Compass.EAST, facing));
		//TODO:  Fire a sound event indicating a step was taken
	}
}
